/*
 * =====================================================================================
 *
 *       Filename:  netHelp.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  07/12/2012 11:43:54 AM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  wangtengchao , wangtengchao AT gmail.com
 *   Organization:  
 *
 * =====================================================================================
 */

#include"netHelp.h"
#include"inetAddr.h"
#include "defines.h"
#include<arpa/inet.h>//for inet_pton inet_ntop
#include<fcntl.h>//for fcntl
#include<sys/types.h>

#ifdef NET_DEBUG
#include<cstdio>
#include<errno.h>
#endif

using namespace inm::net;
in_addr_t inm::net::InetPresentationToNumeric(const char* str)
{
	in_addr_t addr;
    if(1 ==  inet_pton(AF_INET,str,&addr))
	{
		return addr;	
	}	
	else
    {
        return 0;//if error, just return 0
    }
}

string inm::net::InetNumericToPresentation(const in_addr_t& addr)
{
	char sAddr[INET_ADDRSTRLEN] = {'\0'};//INET_ADDRSTRLEN is 16
    if(NULL != inet_ntop(AF_INET,&addr,sAddr,sizeof(sAddr)))
	{
		return string(sAddr);	
	}
	return "";
	
}
/*
string inm::net::InetNumericToPresentation(const InetAddr& inetAddr)
{
    char sAddr[INET_ADDRSTRLEN] = {'\0'};//INET_ADDRSTRLEN is 16
    if(NULL != inet_ntop(AF_INET,&(inetAddr.getInAddr()),sAddr,sizeof(sAddr)))
    {
        return string(sAddr);
    }
    return "";

}
*/

bool inm::net::SetNonBlock(int fd)
{
    int opts;
    opts = fcntl(fd,F_GETFL);
    if(opts < 0)
    {//write log
#ifdef NET_DEBUG
        printf("setnonblock error\n");
#endif
        return false; //get fcntl setting failed
    }
    opts |= O_NONBLOCK;
    if(fcntl(fd,F_SETFL,opts) < 0)
    {
#ifdef NET_DEBUG
        printf("setnonblock error\n");
#endif
        return false;//set failed
    }
    return true;
}

int inm::net::Socket(int family, int type, int protocol)
{
    int sockfd;
    if((sockfd = socket(family,type,protocol)) < 0)
    {//write log
#ifdef NET_DEBUG
        printf("socket error\n");
#endif
    }
    return sockfd;
}
bool inm::net::Bind(int sockfd, const sockaddr_in& myaddr)
{
    if(bind(sockfd,(struct sockaddr*)(&myaddr),sizeof(myaddr)) < 0)
    {//write log   errno is not thread safe .so can not use
#ifdef NET_DEBUG
        printf("bind error :%d\n",errno);
#endif
        return false;
    }
    return true;
}
void inm::net::Listen(int sockfd)
{
    if(listen(sockfd,SOMAXCONN) < 0)//SOMAXCONN is the largest backlog nums
     {//write log
#ifdef NET_DEBUG
        printf("listen error\n");
#endif
    }
}
/*
int inm::net::Accept(int sockfd,  sockaddr_in& peerAddr)
{
    socklen_t len = sizeof(peerAddr);
    int confd;
    if((confd = accept(sockfd,(struct sockaddr*)(&peerAddr),&len)) < 0)
    {//write log
        return -1;
    }
    return confd;
}
*/


int inm::net::Accept(int sockfd,InetAddr& clientAddr)
{
    struct sockaddr_in tempAddr;
    socklen_t len = sizeof(tempAddr);
    int confd;
    if((confd = accept(sockfd,(struct sockaddr*)(&tempAddr),&len)) < 0)
    {//write log
        return -1;//上层将确定是否是真的出错了
    }
    clientAddr.setSockAddr(tempAddr);
    return confd;

}

void inm::net::Close(int fd)
{
    if(close(fd) < 0)
    {//write log
#ifdef NET_DEBUG
        printf("close error\n");
#endif
    }
}

void inm::net::ShutdownWrite(int fd)
{
    if (shutdown(fd, SHUT_WR) < 0)
    {
#ifdef NET_DEBUG
        printf("shutdownwrite\n");
#endif
    }
}

ssize_t inm::net::Write(int fd, const void *buf, size_t count)
{
    ssize_t n;
    if((n=write(fd,buf,count)) <0 )
    {
#ifdef NET_DEBUG
        printf("write return -1\n");//因为是非阻塞，所以不一定是错误，可能是EAGAIN
#endif
    }
    return n;
}
